//
//  Snake.hpp
//  Snake
//
//  Created by CmST0us on 16/11/25.
//  Copyright © 2016年 SpringEngine. All rights reserved.
//

#ifndef Snake_hpp
#define Snake_hpp

#include <stdio.h>
#include "Food.hpp"
#include "Point.hpp"
#include "Frame.hpp"

typedef struct Body{
    typedef struct Body* BodyRef;
    
    static const char headShape = 'x';
    static const char bodyShape = '@';
    static const int  bodyTail  = __INT_MAX__;
    static const int  bodyHead  = 0;
    
    Point point;
    
    char shape;
    Body *front;
    Body *next;
    
    Body(Point point, char shape = Body::bodyShape){
        this->point.x = point.x;
        this->point.y = point.y;
        this->front = nullptr;
        this->next = nullptr;
        this->shape = shape;
    }
    ~Body(){
        this->front = nullptr;
        this->next = nullptr;
    }
    
    void addBody(Point point, int offset, char shape = Body::bodyShape){
        BodyRef pNode = this;
        
        for(int i = 0; i < offset; ++i){
            if(pNode->next == nullptr){
                //pNode is end of chain, but we also add point to the end;
                //create a new body node
                BodyRef bodyNode = new Body(point, shape);
                
                bodyNode->front = pNode;
                pNode->next = bodyNode;
                
                return;
            }else{
                //移动pNode到目标位置
                pNode = pNode->next;
            }
        }
        //insert node at desire index
        
        //create new body Node
        BodyRef bodyNode = new Body(point, shape);
        //move chain
        if(pNode->front == nullptr){
            //pNode top Node
            pNode->shape = Body::bodyShape;
            bodyNode->shape = Body::headShape;
            pNode->front = bodyNode;
            bodyNode->next = pNode;
            
        }else{
            (pNode->front)->next = bodyNode;
            bodyNode->front = (pNode->front)->next;
        }
    };
    
     void delBody(int offset){
        BodyRef pNode = this;
        for(int i = 0; i < offset; i++){
            if(pNode->next == nullptr){
                //pNode is last body node
                //but we still del pNode
                //copy point
//                Point p = pNode->point;
                (pNode->front)->next = nullptr;
                delete pNode;
                return;
            }else{
                //move node
                pNode = pNode->next;
            }
        }
        //del node
        BodyRef prev = pNode->front;
        BodyRef next = pNode->next;
//        Point p = pNode->point;
        prev->next = next;
        next->front = prev;
        
        delete pNode;
        return;
    };
    
    BodyRef searchBody(Point point){
        BodyRef pNode = this;
        for(;;){
            if(pNode->next == nullptr){
                //pNode is last
                if(pNode->point == point){
                    //get target
                    return pNode;
                }else{
                    //last is no desired target
                    return nullptr;
                }
                
            }else{
                if(pNode->point == point)
                    return pNode;
            }
            pNode = pNode->next;
                
        }
        return nullptr;
    };
    
    int bodyLength(){
        BodyRef pNode = this;
        for(int i = 1; ; i++){
            if(pNode->next == nullptr){
                return i;
            }else{
                pNode = pNode->next;
            }
        }
    };
}Body;
typedef struct Body* BodyRef;


typedef struct Direction{
    int x;
    int y;
    
}Direction;
class Snake{
public:
    typedef enum MOVE_STATE{
        STATE_NORMAL = 0,
        STATE_FOOD = 1,
        STATE_SELFKILL = 2,
        STATE_WALL = 3
    }MOVE_STATE;
    
    
    BodyRef _body;
    Direction _direction;
    Snake();
    
public:
    MOVE_STATE move(FoodRef food, const Frame& frame);
    void bodyToHead();
private:
    
};
#endif /* Snake_hpp */
